package com.bpzj.util.datetime;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.Date;

// TODO 完善 dateUtils

/**
 * Jdk 8以后尽量使用 LocalDateTime, LocalDate, LocalTime ; 尽量不使用 Date <br>
 * 如果使用 LocalDateTime， 格式化时， 必须使用 DateTimeFormatter 类的静态实例 <br>
 * 如下：<br>
 * yyyy-MM-dd               {@link DateTimeFormatter#ISO_LOCAL_DATE}  <br>
 * yyyyMMdd                 {@link DateTimeFormatter#BASIC_ISO_DATE}  <br>
 * 2011-12-03T10:15:30      {@link DateTimeFormatter#ISO_LOCAL_DATE_TIME}
 * <p>
 * @author bpzj 2020-8-23
 */
public final class DateTimeUtils {

    public static final String DEFAULT_PATTERN = "yyyy-MM-dd HH:mm:ss";
    public static final String DEFAULT_PATTERN_DATE = "yyyy-MM-dd";
    public static final String yymmdd = "yyMMdd";
    public static final String yyyyMMddHHmmss = "yyyyMMddHHmmss";
    /** yyyy-MM-dd 形式的日期 */
    public static final DateTimeFormatter DEFAULT_DATE_PATTERN = DateTimeFormatter.ISO_LOCAL_DATE;
    /** yyyy-MM-dd HH:mm:ss 的形式 */
    public static final DateTimeFormatter DEFAULT_DATE_TIME_PATTERN = DateTimeFormatter.ofPattern(DEFAULT_PATTERN);

    private final static Logger log = LoggerFactory.getLogger(DateTimeUtils.class);

    private DateTimeUtils() {
    }

    /**
     * 把 yyyy-MM-dd格式字符串转为 LocalDateTime, time使用默认 0:00
     * @param date 必须为 yyyy-MM-dd日期格式字符串, 如 2020-12-12
     * @return LocalDateTime
     */
    public static LocalDateTime parseLocalDateTimeOfDate(String date) {
        if (isEmpty(date)) return null;
        return LocalDateTime.of(LocalDate.parse(date, DEFAULT_DATE_PATTERN), LocalTime.of(0, 0));
    }

    /**
     * 把 "日期格式" 字符串转为 LocalDateTime, time使用默认 0:00
     * @param date    日期格式字符串, 如 2020-12-12, 不能有时间
     * @param pattern 日期格式, yyyy-MM-dd
     * @return LocalDateTime
     */
    public static LocalDateTime parseLocalDateTimeOfDate(String date, String pattern) {
        if (isEmpty(date)) return null;
        try {
            LocalDate localDate = LocalDate.parse(date, DateTimeFormatter.ofPattern(pattern));
            return LocalDateTime.of(localDate, LocalTime.of(0, 0));
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 把 日期+时间 格式字符解析为 LocalDateTime
     * 此方法为多余， 调用者应该写为
     * String dateTime = ....;
     * LocalDateTime dateTime = StringUtils.isEmpty(dateTime) ? null: LocalDateTime.parse(dateTime, DEFAULT_DATE_TIME_PATTERN);
     */
    public static LocalDateTime parseLocalDateTime(String dateTime) {
        if (isEmpty(dateTime)) {
            return null;
        } else {
            return LocalDateTime.parse(dateTime, DEFAULT_DATE_TIME_PATTERN);
        }
    }

    /**
     * 此方法多余， 日期解析出错， 不应该被 catch 之后返回 null
     */
    public static LocalDateTime parseLocalDateTime(String dateTime, String pattern) {
        try {
            return LocalDateTime.parse(dateTime, DateTimeFormatter.ofPattern(pattern));
        } catch (Exception e) {
            log.error("解析日期出错", e);
        }
        return null;
    }

    public static String format(LocalDate date) {
        if (date == null) {
            return "";
        }
        if (DEFAULT_DATE_PATTERN == DateTimeFormatter.ISO_LOCAL_DATE) {
            return date.toString();
        }
        return DEFAULT_DATE_PATTERN.format(date);
    }

    public static String format(LocalDate date, String pattern) {
        if (date == null) {return "";};
        return DateTimeFormatter.ofPattern(pattern).format(date);
    }

    /**
     * LocalDateTime 格式化为日期形式, 使用 DEFAULT_DATE_PATTERN
     * @param dateTime LocalDateTime 格式
     * @return 默认日期形式, 不含时间
     */
    public static String formatToDate(LocalDateTime dateTime) {
        if (dateTime == null) {
            return "";
        }
        if (DEFAULT_DATE_PATTERN == DateTimeFormatter.ISO_LOCAL_DATE) {
            return dateTime.toLocalDate().toString();
        }
        return DEFAULT_DATE_PATTERN.format(dateTime.toLocalDate());
    }

    /**
     * LocalDateTime 格式化为 给定参数形式
     * @param dateTime LocalDateTime
     * @param pattern 形式
     * @return
     */
    public static String format(LocalDateTime dateTime, String pattern) {
        if (dateTime == null) {
            return "";
        }
        return DateTimeFormatter.ofPattern(pattern).format(dateTime);
    }


    public static String covertTimeStamp2String(Timestamp s) {
        DateFormat sdf = new SimpleDateFormat(DEFAULT_PATTERN);
        return sdf.format(s);
    }


    public static Date parseDate(String date, String patten) {
        DateFormat sdf = new SimpleDateFormat(patten);
        try {
            return sdf.parse(date);
        } catch (ParseException e) {
        }
        return null;
    }

    public static Date parseDate(String date) {
        DateFormat sdf = new SimpleDateFormat(DEFAULT_PATTERN);
        try {
            return sdf.parse(date);
        } catch (ParseException e) {
        }
        return null;
    }



    public static LocalDateTime parseLocalDate(String date) {
        if (isEmpty(date)) {
            return null;
        }
        return LocalDateTime.of(LocalDate.parse(date), LocalTime.MIN);
    }

    public static String format(Date date, String partten) {
        if (date == null) {
            return "";
        }
        DateFormat sdf = new SimpleDateFormat(partten);
        return sdf.format(date);
    }

    public static String format(Date date) {
        if (date==null) {
            return "";
        }
        DateFormat sdf = new SimpleDateFormat(DEFAULT_PATTERN);
        return sdf.format(date);
    }

    public static String formatDate(Date date) {
        if (date==null) {
            return "";
        }
        DateFormat sdf = new SimpleDateFormat(DEFAULT_PATTERN_DATE);
        return sdf.format(date);
    }



    public static LocalDate getPropertyDate(Integer inputDate) {
        if (99999999 == inputDate) {
            return LocalDate.of(2999, 1, 1);
        }
        if (inputDate <= 0) {
            return LocalDate.of(0, 1, 1);
        }
        int day = inputDate % 100;
        int year = (inputDate - inputDate % 10000) / 10000;
        int month = (inputDate - year * 10000 - day) / 100;
        return LocalDate.of(year, month, day);
    }


    public static void main(String[] args) {
        LocalDateTime localDateTime = parseLocalDateTime("20201230115900", "yyyyMMddHHmmss");
        System.out.println("-" + localDateTime);
        System.out.println(DateTimeFormatter.ISO_LOCAL_DATE.format(LocalDateTime.now()));

        String date = formatToDate(LocalDateTime.now());
        System.out.println(date);
    }

    /** 不要调用此函数，直接书写函数体 */
    public static String todayISOFormatString() {
        return LocalDate.now().toString();
    }


    public static LocalDateTime stringLocalDateToNextTime(String date) {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(DEFAULT_PATTERN_DATE);
        if (isEmpty(date)) {
            return null;
        }
        return LocalDateTime.of(LocalDate.parse(date, dateTimeFormatter), LocalTime.of(23, 59, 59));
    }

    private static boolean isEmpty(String date) {
        return date != null && date.length() > 0;
    }
}
